home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1994 November: Tool Chest / Dev.CD Nov 94.toast / Tool Chest / Toolbox / APPL loads APPL / OldAppl.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-09-01  |  9.5 KB  |  367 lines  |  [TEXT/MPS ]

  1. /*
  2.     © Copyright 1990 Apple Computer, Inc.   All Rights Reserved.
  3.     
  4.     Programmed by Ricardo Batista, 07/06/90
  5.     
  6.     
  7.     This is a test application.
  8.     The idea is to be able to load and execute an application from a 4D external or
  9.     HyperCard XCMD.  The reason is that we need to be able to use the library code
  10.     from TMS, which uses global code and requires a jump table.
  11.     TMS harcoded in assembly language references trough a5, therefore requiring a
  12.     jump table, if the code had been compiled with C or Pascal, the code could have
  13.     been recompiled to use PC relative references, making the tms library compatible
  14.     with code resources such as externals for 4D and HyperCard.
  15.     
  16.     Our workaround consists of creating an application inside an application.
  17.     Sounds scary huh ?
  18.     All we need to do is make a pointer big enough to hold an application, initialize
  19.     a new heap zone, setup a stack, an a5 world, load the application and save some
  20.     low memory global variables.
  21.     
  22.     To communicate with the application we will pass a parameter block pointer at the
  23.     base of the stack, making it easy to access for the application.
  24.     
  25.     Notice that the application must not call GetNextEvent or WaitNextEvent, the
  26.     reason is that MultiFinder will reset the stack and the current heap to the original
  27.     heap and stack of the parent application.  What does this mean ?  It means that as
  28.     soon as the call to GetNextEvent returns, the application will be using the wrong stack
  29.     and heap. (read it as in trash memory, would ya ?)
  30.     
  31.     In fact, the application we call should not try to make dialog boxes or anything like
  32.     that, we just want the application to compress and decompress images, ok ?
  33.     
  34.     Also, the application should not call ExitToShell, just quit by ending the main loop.
  35.     
  36.     The code in this file could be modified to patch ExitToShell (for quitting) and
  37.     GetNextEvent-WaitNextEvent so we could save and restore the real stack and heap, but
  38.     hey, I don't have the need or the time.
  39.     
  40.     This is a map of how memory looks:
  41.     
  42.     
  43.     ------------------------- Main Application heap zone END ( $400 as an example)
  44.     |                        |
  45.     | A5, jump table, etc.. |
  46.     |                        |
  47.     ------------------------- Sub Application space END ($300 as an example)
  48.         | Above a5         |
  49.         -----------------    <-- a5
  50.         | Jump Table    |
  51.         -----------------
  52.         | Below a5        |
  53.         -----------------    <-- Stack Base
  54.         | Stack            |
  55.         -----------------    <-- Stack END, Application limit
  56.         | Memory avail. |
  57.         |   for heap    |
  58.         -----------------     <-- Initial Heap END
  59.         | Zone Trailer  |
  60.         -----------------
  61.         | Heap Zone        |
  62.         -----------------
  63.         | Zone Header    |
  64.     ------------------------- <-- Sub Application Heap Zone Begin, space Begin, ($200 as an example)
  65.     |                        |
  66.     | Main App Heap Zone    |
  67.     |                        |
  68.     ------------------------- <-- Main application Heap Zone Begin, ($100 as an example)
  69.     
  70.     
  71.     The idea is that once the new world has been created for the tms processing application it
  72.     will be kept around until it is no longer needed, we could patch GetNextEvent and take that
  73.     as a signal that the process is done, resuming the call to GetNextEvent when we need to call
  74.     the tms functions again.
  75. */
  76.  
  77.  
  78. #include "Types.h"
  79. #include "Memory.h"
  80. #include "OSUtils.h"
  81. #include "Resources.h"
  82. #include "Files.h"
  83. #include "SysEqu.h"
  84.  
  85. #include "Packages.h"
  86. #include "Dialogs.h"
  87. #include "Fonts.h"
  88. #include "Menus.h"
  89.  
  90.  
  91.  
  92. typedef struct {
  93.     unsigned long aboveA5;
  94.     unsigned long belowA5;
  95.     unsigned long JTSize;
  96.     unsigned long JTOffset;
  97.     unsigned long jumpTable[10];
  98. } *code0Ptr;
  99.  
  100.  
  101.  
  102.  
  103.  
  104. typedef struct {
  105.     Handle             oldTopMapHandle;
  106.     Handle             newTopMapHandle;
  107.     long             oldA5;
  108.     long             newA5;
  109.     long             oldJTOffset;
  110.     long             newJTOffset;
  111.     Handle             oldCodeHandle;
  112.     Handle             newCodeHandle;
  113.     short             oldApRefNum;
  114.     short             newApRefNum;
  115.     short            oldVol;
  116.     short            newVol;
  117.     long            oldHiHeapMark;
  118.     long            newHiHeapMark;
  119.     long            oldHeapEnd;
  120.     long            newHeapEnd;
  121.     long            oldStackBase;
  122.     long            newStackBase;
  123.     Ptr                oldApplLimit;
  124.     Ptr                newApplLimit;
  125.  
  126.     Ptr                newZone;
  127.     THz                oldZone;
  128. } Inside, *InsidePtr;
  129.  
  130.  
  131.  
  132.  
  133.  
  134. long GetApplication(short *oldVol, short *file);
  135. void GetOldInfo(InsidePtr info);
  136. void SetInfo(InsidePtr info, Boolean new);
  137.  
  138.  
  139.  
  140. // A test for a growZone procedure, I don't really want to do anything here
  141.  
  142. pascal long myProc(long needed)
  143. {
  144.     DebugStr("\pGrowProc");
  145.     return(needed);
  146. }
  147.  
  148.  
  149.  
  150.  
  151. // Main test program, set up the new world and switch worlds
  152.  
  153. void main(void) {
  154.     InsidePtr info;
  155.     unsigned long memNeeded;
  156.     Handle code;
  157.     code0Ptr code0;
  158.     unsigned long endOfStack;
  159.     
  160.     // for this test only
  161.         MaxApplZone();
  162.         InitGraf(&qd.thePort);
  163.         InitFonts();
  164.         InitWindows();
  165.         TEInit();
  166.         InitDialogs(0L);
  167.         InitMenus();
  168.         DrawMenuBar();
  169.     // end this test only
  170.     // if not previously loaded
  171.         info = (InsidePtr) NewPtr(sizeof(Inside));
  172.         GetOldInfo(info);
  173.         memNeeded = GetApplication(&(info->oldVol), &(info->newApRefNum));
  174.         if (!memNeeded) {
  175.             *((Handle*) TopMapHndl) = info->oldTopMapHandle;
  176.             return;
  177.         }
  178.         info->newZone = NewPtr(memNeeded);
  179.         if (!info->newZone) {
  180.             CloseResFile(info->newApRefNum);
  181.             *((Handle*) TopMapHndl) = info->oldTopMapHandle;
  182.             SetVol(0L, info->oldVol);
  183.             return;
  184.         }
  185.         InitZone(myProc, 64, (Ptr) ((long) info->newZone + 8192L), info->newZone);    // TheZone changed
  186.         SetResLoad(true);
  187.         code = Get1Resource('CODE', 0);
  188.         if (!code) {
  189.             SetZone(info->oldZone);
  190.             DisposPtr(info->newZone);
  191.             CloseResFile(info->newApRefNum);
  192.             *((Handle*) TopMapHndl) = info->oldTopMapHandle;
  193.             SetVol(0L, info->oldVol);
  194.             return;
  195.         }
  196.         HLock(code);
  197.         code0 = (code0Ptr) *code;
  198.         info->newA5 = (long) info->newZone + memNeeded - code0->aboveA5;
  199.         if (info->newA5 % 4)
  200.             info->newA5 -= 2;    // make it long word aligned
  201.         info->newJTOffset = code0->JTOffset;
  202.         info->newStackBase = info->newA5 - code0->belowA5;
  203.         endOfStack = info->newStackBase - 16248L;
  204.         info->newApplLimit = (Ptr) endOfStack;
  205.         // SetApplLimit((Ptr) endOfStack);
  206.         BlockMove((Ptr) &(code0->jumpTable[0]), (Ptr) (info->newA5 + code0->JTOffset),
  207.                 code0->JTSize);
  208.         info->newCodeHandle = code;
  209.         info->newTopMapHandle = *((Handle*) TopMapHndl);
  210.         *((char*) WWExist) = false;
  211.         *((char*) QDExist) = false;
  212.         info->newHiHeapMark = ((THz) TheZone)->bkLim;
  213.         info->newHeapEnd = ((THz) TheZone)->bkLim;
  214.         InitAllPacks();
  215.     // end if not previously loaded
  216.     
  217.     info->oldHiHeapMark = *((long*) HiHeapMark);
  218.     info->oldHeapEnd = *((long*) HeapEnd);    
  219.     SetInfo(info, true);        // true for new info
  220.     
  221.     GOTOAPP();
  222.     
  223.     info->newHiHeapMark = *((long*) HiHeapMark);
  224.     info->newHeapEnd = *((long*) HeapEnd);
  225.     SetInfo(info, false);        // restore old info
  226.     *((char*) WWExist) = true;
  227.     *((char*) QDExist) = true;
  228.     // if this was for the last time...
  229.         *((Handle*) TopMapHndl) = info->newTopMapHandle;
  230.         CloseResFile(info->newApRefNum);
  231.         *((Handle*) TopMapHndl) = info->oldTopMapHandle;
  232.         DisposPtr(info->newZone);
  233.         DisposPtr((Ptr) info);
  234.     // end if for the last time
  235. }
  236.  
  237.  
  238.  
  239.  
  240.  
  241.  
  242. //
  243. // Get the global information for the current process
  244. //
  245.  
  246. void GetOldInfo(InsidePtr info)
  247. {
  248.     info->oldTopMapHandle = *((Handle*) TopMapHndl);
  249.     info->oldA5 = *((long*) CurrentA5);
  250.     info->oldJTOffset = *((short*) CurJTOffset);
  251.     info->oldCodeHandle = *((Handle*) SaveSegHandle);
  252.     info->oldApRefNum = *((short*) CurApRefNum);
  253.     info->oldZone = GetZone();
  254.     info->oldStackBase = *((long*) CurStackBase);
  255.     info->oldApplLimit = *((Ptr*) ApplLimit);
  256. }
  257.  
  258.  
  259.  
  260.  
  261. //
  262. // Set the global information for either the original or the enclosed
  263. // application.  This enables the applications to run independently,
  264. // without corrupting the other one.
  265.  
  266. void SetInfo(InsidePtr info, Boolean new)
  267. {
  268.     if (new) {
  269.         *((Handle*) TopMapHndl) = info->newTopMapHandle;
  270.         *((long*) CurrentA5) = info->newA5;
  271.         *((short*) CurJTOffset) = info->newJTOffset;
  272.         *((Handle*) SaveSegHandle) = info->newCodeHandle;
  273.         *((short*) CurApRefNum) = info->newApRefNum;
  274.         *((long*) CurStackBase) = info->newStackBase;
  275.         SetZone((THz) info->newZone);
  276.         *((long*) HiHeapMark) = info->newHiHeapMark;
  277.         *((long*) HeapEnd) = info->newHeapEnd;
  278.         *((Ptr*) ApplZone) = info->newZone;
  279.         *((Ptr*) ApplLimit) = info->newApplLimit;
  280.     }
  281.     else {
  282.         *((Handle*) TopMapHndl) = info->oldTopMapHandle;
  283.         *((long*) CurrentA5) = info->oldA5;
  284.         *((short*) CurJTOffset) = info->oldJTOffset;
  285.         *((Handle*) SaveSegHandle) = info->oldCodeHandle;
  286.         *((short*) CurApRefNum) = info->oldApRefNum;
  287.         *((long*) CurStackBase) = info->oldStackBase;
  288.         SetZone(info->oldZone);
  289.         *((long*) HiHeapMark) = info->oldHiHeapMark;
  290.         *((long*) HeapEnd) = info->oldHeapEnd;
  291.         *((Ptr*) ApplZone) = (Ptr) info->oldZone;
  292.         *((Ptr*) ApplLimit) = info->oldApplLimit;
  293.     }
  294. }
  295.  
  296.  
  297.  
  298.  
  299.  
  300.  
  301. //
  302. // Select an application to load
  303. // check on its size resource and make sure we have enough memory
  304. // to load that application, also set the volume and resource file
  305. //
  306.  
  307. long GetApplication(short *oldVol, short *file)
  308. {
  309.     long prefSize = 524288L, minSize = 524288L;
  310.     long mem;
  311.     SFReply reply;
  312.     SFTypeList fTypes;
  313.     Point where;
  314.     register short err;
  315.     Handle H;
  316.     
  317.     fTypes[0] = 'APPL';
  318.     where.h = where.v = 100;
  319.     SFGetFile(where, "\p", 0L, 1, fTypes, 0L, &reply);
  320.     if (!reply.good)
  321.         return (0L);
  322.     err = GetVol(0L, oldVol);
  323.     err = SetVol(0L, reply.vRefNum);
  324. // *((Handle*) TopMapHndl) = 0L;
  325.     *file = OpenResFile(reply.fName);
  326.     if (*file == -1) {
  327.         DebugStr("\pOpenFile");
  328.         SysBeep(1);
  329.         SetVol(0L, *oldVol);
  330.         return (0L);
  331.     }
  332.     H = Get1Resource('SIZE', -1);
  333.     if (H) {
  334.         LoadResource(H);
  335.         HLock(H);
  336.         BlockMove(*H + (Ptr) 2L, (Ptr) &prefSize, 4L);
  337.         BlockMove(*H + (Ptr) 6L, (Ptr) &minSize, 4L);
  338.         HUnlock(H);
  339.         ReleaseResource(H);
  340.     }
  341.     mem = MaxBlock();
  342.     if (mem > prefSize)
  343.         mem = prefSize;
  344.     else {
  345.         if (mem > minSize)
  346.             mem = minSize;
  347.         else
  348.             mem = 0L;
  349.     }
  350.     if (!mem) {
  351.         DebugStr("\pMemory");
  352.         SysBeep(1);
  353.         CloseResFile(*file);
  354.         SetVol(0L, *oldVol);
  355.     }
  356.     return(mem);
  357. }
  358.  
  359.  
  360.  
  361.  
  362.  
  363.  
  364.  
  365.  
  366.  
  367.